#include <IntroState.h>

template<> IntroState* Ogre::Singleton<IntroState>::ms_Singleton = 0;

void IntroState::enter()
{
  _root = Ogre::Root::getSingletonPtr();

  // Se recuperan el gestor y la cámara
  _sceneMgr = _root->getSceneManager("SceneManager");
  _camera = _sceneMgr->getCamera("MainCamera");
  _win = _root->getAutoCreatedWindow();
  _viewport = _win->addViewport(_camera);
  _viewport->setBackgroundColour(Ogre::ColourValue(0.0, 0.0, 0.0));

  // Posicionamos la cámara
  _camera->setPosition(Ogre::Vector3(0,0,75));
  _camera->lookAt(Ogre::Vector3(0,0,0));
  _camera->setNearClipDistance(5);
  _camera->setFarClipDistance(10000);

  _viewport->setBackgroundColour(Ogre::ColourValue(0.0,0.0,0.0));
  double width = _viewport->getActualWidth();
  double height = _viewport->getActualHeight();
  _camera->setAspectRatio(width / height);

  _exitGame = false;
  _overlayMgr = Ogre::OverlayManager::getSingletonPtr();
  _mouseOverlay = _overlayMgr->getOverlayElement("cursor");

  _playSelected = false;
  _recordsSelected = false;
  _creditsSelected = false;
  _quitSelected = false;
  _somethingSelected = false;

  std::fstream fs;
  unsigned int n;
  _records = new std::list<unsigned int>;

  fs.open("records", std::ios::in);
  if (not fs.fail())
    while (fs.good())
    {
      fs >> n;
      _records->push_back(n);
    }
  fs.close();

  // Mostrar overlays del menu
  viewOverlays();
}

void IntroState::exit()
{
  _sceneMgr->clearScene();
  _root->getAutoCreatedWindow()->removeAllViewports();

  std::fstream fs;
  std::list<unsigned int>::iterator it;

  fs.open("records", std::ios::out | std::ios::trunc);
  
  for (it = _records->begin(); it != _records->end(); it++)
    fs << " " << *it;
 
  fs.close(); 
  delete _records;
}

void IntroState::pause()
{
  _overlayMgr->getOverlayElement("menuImage")->hide();
  _overlayMgr->getOverlayElement("menuPlayImage")->hide();
  _overlayMgr->getOverlayElement("menuCreditsImage")->hide();
  _overlayMgr->getOverlayElement("menuRecordsImage")->hide();
  _overlayMgr->getOverlayElement("menuQuitImage")->hide();
  _overlayMgr->getByName("Cursor")->hide();
}

void IntroState::resume()
{
  _sceneMgr->clearScene();
  viewOverlays();
}

void IntroState::keyPressed(const OIS::KeyEvent &e)
{
  if (e.key == OIS::KC_ESCAPE)
    _exitGame = true;
}

void IntroState::keyReleased(const OIS::KeyEvent& e) {}

void IntroState::mouseMoved(const OIS::MouseEvent& e)
{
  _mouseOverlay->setLeft(e.state.X.abs);
  _mouseOverlay->setTop(e.state.Y.abs);
}

void IntroState::mousePressed(const OIS::MouseEvent& e, OIS::MouseButtonID id)
{
  unsigned int posx = e.state.X.abs;
  unsigned int posy = e.state.Y.abs;

  // Pulsar Botón jugar
  if (mouseInPlay(posx, posy))
  {
    _overlayMgr->getOverlayElement("menuPlayImage")->show();
    _playSelected = true;
    _somethingSelected = true;
  }

  // Pulsar Botón records
  if (mouseInRecords(posx, posy))
  {
    _overlayMgr->getOverlayElement("menuRecordsImage")->show();
    _recordsSelected = true;
    _somethingSelected = true;
  }

  // Pulsar Botón créditos
  if (mouseInCredits(posx, posy))
  {
    _overlayMgr->getOverlayElement("menuCreditsImage")->show();
    _creditsSelected = true;
    _somethingSelected = true;
  }

  // Pulsar Botón salir
  if (mouseInQuit(posx, posy))
  {
    _overlayMgr->getOverlayElement("menuQuitImage")->show();
    _quitSelected = true;
    _somethingSelected = true;
  }
}

void IntroState::mouseReleased(const OIS::MouseEvent& e, OIS::MouseButtonID id)
{
  if (not _somethingSelected) return;
  _somethingSelected = false;

  unsigned int posx = e.state.X.abs;
  unsigned int posy = e.state.Y.abs;

  // Hay que sacar los hide() fuera de los if para que si soltamos
  // fuera del botón no se quede marcado
  _overlayMgr->getOverlayElement("menuCreditsImage")->hide();
  _overlayMgr->getOverlayElement("menuPlayImage")->hide();
  _overlayMgr->getOverlayElement("menuRecordsImage")->hide();
  _overlayMgr->getOverlayElement("menuQuitImage")->hide();

  // Soltar Botón jugar
  if (mouseInPlay(posx, posy) and _playSelected)
  {
    _playSelected = false;
    pushState(PlayState::getSingletonPtr());
    return;
  }

  // Soltar Boton Salir
  if (mouseInQuit(posx, posy) and _quitSelected)
  {
    _quitSelected = false;
    _exitGame = true;
    return;
  }

  // Soltar Botón records
  if (mouseInRecords(posx, posy) and _recordsSelected)
  {
    _recordsSelected = false;
    ExtrasState* e = ExtrasState::getSingletonPtr();
    e->setType(Records);
    pushState(e);
    return;
  }

  // Soltar Botón créditos
  if (mouseInCredits(posx, posy) and _creditsSelected)
  {
    _creditsSelected = false;
    ExtrasState* e = ExtrasState::getSingletonPtr();
    e->setType(Credits);
    pushState(e);
    return;
  }
}

bool IntroState::frameStarted(const Ogre::FrameEvent& evt) 
{
  return true;
}

bool IntroState::frameEnded(const Ogre::FrameEvent& evt)
{
  return not _exitGame;
}

void IntroState::viewOverlays()
{
  _overlayMgr->getByName("Cursor")->show();
  _overlayMgr->getByName("GUI")->show();
  
  _overlayMgr->getOverlayElement("menuImage")->show();
  _overlayMgr->getByName("Screen")->hide();
  _overlayMgr->getOverlayElement("menuPlayImage")->hide();
  _overlayMgr->getOverlayElement("menuCreditsImage")->hide();
  _overlayMgr->getOverlayElement("menuRecordsImage")->hide();
  _overlayMgr->getOverlayElement("menuQuitImage")->hide();
  _overlayMgr->getOverlayElement("Records")->hide();
  _overlayMgr->getOverlayElement("Credits")->hide();
}

bool IntroState::mouseInPlay(const int posx, const int posy)
{
  return ((posx > (658 * _win->getWidth() / 1280)) and
          (posx < (843 * _win->getWidth() / 1280)) and
          (posy > (414 * _win->getHeight() / 800)) and
          (posy < (460 * _win->getHeight() / 800)));
}

bool IntroState::mouseInRecords(const int posx, const int posy)
{
  return ((posx > (595 * _win->getWidth() / 1280)) and
          (posx < (904 * _win->getWidth() / 1280)) and
          (posy > (507 * _win->getHeight() / 800)) and
          (posy < (546 * _win->getHeight() / 800)));
}

bool IntroState::mouseInCredits(const int posx, const int posy)
{
  return ((posx > (612 * _win->getWidth() / 1280)) and
          (posx < (889 * _win->getWidth() / 1280)) and
          (posy > (604 * _win->getHeight() / 800)) and
          (posy < (645 * _win->getHeight() / 800)));
}

bool IntroState::mouseInQuit(const int posx, const int posy)
{
  return ((posx > (675 * _win->getWidth() / 1280)) and
          (posx < (829 * _win->getWidth() / 1280)) and
          (posy > (699 * _win->getHeight() / 800)) and
          (posy < (742 * _win->getHeight() / 800)));
}

std::list<unsigned int>* IntroState::getRecords()
{
  return _records;
}

IntroState* IntroState::getSingletonPtr()
{
  return ms_Singleton;
}

IntroState& IntroState::getSingleton()
{ 
  assert(ms_Singleton);
  return *ms_Singleton;
}
